package stfin.install.utility;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

public class Installator {

	private final String UNINSTALL_EXECUTABLE_NAME = "uninstall.jar";
	private final String META_DATA_LOCATION = ".statizo";
	private final String INSTALL_LOCATION = "install.location";
	private final String DATA_LOCATION = "data.location";
	
	private final String EXECUTABLE_NAME = "statizo-financeiro.jar";
	
	private final String META_DATA_FILE_NAME = "statizo-install.info";
	private final String INI_FILE = "statizo.ini";

	private final String DATA_DIR_NAME = "data";
	
	private final String fileSeparator = System.getProperty("file.separator");
	private String metaDataDir;
	private boolean installed;
	
	private String installationDir;
	private String installationDataDir;
	
	private String defaultInstallationDir;
	
	private ResourceBundle bundle;
	
	public Installator() throws IOException {
		
		bundle = ResourceBundle.getBundle("messages", new Locale("pt","BR"));
		
		
		String OS = System.getProperty("os.name");
		if(OS.contains("WIN")){
			metaDataDir = System.getenv("AppData");
		}else{
			metaDataDir = System.getProperty("user.home");
		}

		Properties properties = getMetaInfo(false);
		installed = properties != null;
		
		if(installed){
			
			installationDir = properties.getProperty(INSTALL_LOCATION);
			
			properties = getConfigInfo( installationDir );
			
			installationDataDir = properties.getProperty(DATA_LOCATION);
			
		}else{
			
			installationDir = metaDataDir + fileSeparator + META_DATA_LOCATION;
			installationDataDir = normalizeDataDir(installationDir);
			
		}
		
		defaultInstallationDir = installationDir;

	}
	
	/**
	 * Retorna o arquivo properties de meta dados. No linux, em /home/<user>. No Windows, em AppData.
	 * @param create
	 * @return
	 * @throws IOException
	 */
	private Properties getMetaInfo(boolean create) throws IOException{
		File file = getMetaDataFile(create);
		if(file != null && file.exists()){
			InputStream is = new FileInputStream(file);
			Properties properties = new Properties();
			properties.load(is);
			is.close();
			return properties;
		}
		return null;
	}
	

	private Properties getConfigInfo(String path) throws IOException{
		File file = new File(path + fileSeparator + INI_FILE);
		if(file.exists()){
			InputStream is = new FileInputStream(file);
			Properties properties = new Properties();
			properties.load(is);
			is.close();
			return properties;
		}
		return null;
	}
	

	private File getMetaDataFile( boolean create ){
		File metaDataDirectory = makeMetaDataDirectory( create );
		return new File(metaDataDirectory, META_DATA_FILE_NAME);
	}
	

	private File makeMetaDataDirectory(){
		return makeMetaDataDirectory(true);
	}
	

	private File makeMetaDataDirectory(boolean forceCreate){
		File file = new File(metaDataDir + fileSeparator + META_DATA_LOCATION);
		
		if(forceCreate && !file.exists())
			file.mkdirs();
		
		return file;		
	}
	
	public String getDefaultInstallationDir() {
		return defaultInstallationDir;
	}
	
	public String getInstallationDataDir() {
		return installationDataDir;
	}
	
	public String normalizeDataPath(String path){
		return path + fileSeparator + DATA_DIR_NAME;
	}
	
	public boolean isInstalled(){
		return installed;
	}
	
	public void install(String systemLocation, String dbLocation) throws IOException{
		
		File file = makeMetaDataDirectory();
		OutputStream os = new FileOutputStream(file + fileSeparator + META_DATA_FILE_NAME);
		Properties  properties = new Properties();
		properties.put(INSTALL_LOCATION, systemLocation);
		
		properties.store(os, bundle.getString("install-file.warn"));
		
		os.flush();
		os.close();
		
		file = new File(systemLocation);
		file.mkdirs();
		
		file = new File(file, "statizo.ini");
		
		os = new FileOutputStream(file);
		
		properties = new Properties();
		properties.put(DATA_LOCATION, dbLocation);
		properties.store(os, "#Statízo Financeiro Config File#");
		os.close();
		
		InputStream jarFile = getClass().getResourceAsStream("/statizo-financeiro-desktop-BETA-jar-with-dependencies.jar");
		File destFile = new File(systemLocation + fileSeparator + EXECUTABLE_NAME);
		
		destFile.createNewFile();
		destFile.setExecutable(true,false);
		
		os = new FileOutputStream(destFile);
		IOUtils.copyLarge(jarFile, os);		
		jarFile.close();
		os.flush();
		os.close();
		
		
		file = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
		jarFile = new FileInputStream(file);

		destFile = new File(systemLocation + fileSeparator + UNINSTALL_EXECUTABLE_NAME);
		destFile.createNewFile();
		destFile.setExecutable(true, false);
		
		os = new FileOutputStream(destFile);
		IOUtils.copyLarge(jarFile, os);
		jarFile.close();
		os.flush();
		os.close();
		
	}
	
	public String normalizeDataDir(String path){
		return path + fileSeparator + DATA_DIR_NAME;
	}
	
	public void uninstall(boolean widthData) throws IOException{

		Properties properties = getMetaInfo(false);
		
		File installDirectory = new File(properties.getProperty(INSTALL_LOCATION));
		
		String[]childs = installDirectory.list(); 
		
		boolean removeDirectory = true;
		
		for(int i = 0; i<childs.length; i++){
			
			String child = childs[i];
			
			if(child.equals(DATA_DIR_NAME)){
				if(!widthData){
					removeDirectory = false;
				}else{
					FileUtils.deleteDirectory(new File(installDirectory,child));
				}
			}else{
				new File(installDirectory, child).delete();	
			}
			
		}
		
		if(removeDirectory){
			installDirectory.delete();
		}
	
		File metaFile = getMetaDataFile( false );
		FileUtils.deleteDirectory(metaFile.getParentFile());
		metaFile.getParentFile().delete();
		
	}

	public ResourceBundle getBundle() {
		return bundle;
	}
	
	
}